﻿using D.UtilOrm;
using FreeSql;
using FreeSql.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.ComponentModel.DataAnnotations;
using DataType = FreeSql.DataType;

namespace D.UtilFreeSqlOrm
{
    public static class FreeSqlOrm 
    { 
        /// <summary>
        /// 添加ORM以及数据库
        /// </summary>
        /// <param name="services"></param>
        /// <param name="appConfig"></param>
        public async static void AddFreeSql(this IServiceCollection services, DbConfig dbConfig)
        {
            try
            {
                //创建数据库
                if (dbConfig.IsCreateDb)
                {
                    await CreateDatabase(dbConfig);
                }

                var dbType = GetDbType(dbConfig.DbType);

                var freeSqlBuilder = new FreeSqlBuilder()
                        .UseNameConvert(NameConvertType.ToLower)
                        .UseConnectionString(dbType, dbConfig.ConnectionString)
                        .UseAutoSyncStructure(dbConfig.SyncStructure) //自动迁移实体的结构到数据库
                        .UseLazyLoading(false)
                        .UseNoneCommandParameter(true);

                var fsql = freeSqlBuilder.Build();
                services.AddScoped<IUnitOfWork>(sp => fsql.CreateUnitOfWork());
                services.AddSingleton(fsql);

                #region 监听所有命令
                if (dbConfig.MonitorCommand)
                {
                    freeSqlBuilder.UseMonitorCommand(cmd => { }, (cmd, traceLog) =>
                    {
                        Console.WriteLine($"{cmd.CommandText}\n{traceLog}\r\n");
                    });
                }
                #endregion

                #region 监听Curd操作
                if (dbConfig.Curd)
                {
                    fsql.Aop.CurdBefore += (s, e) =>
                    {
                        Console.WriteLine($"{e.Sql}\r\n");
                    };
                }
                #endregion
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 创建数据库
        /// </summary>
        /// <param name="dbConfig"></param>
        /// <returns></returns>
        public async static Task CreateDatabase(DbConfig dbConfig)
        {
            var dbType = GetDbType(dbConfig.DbType);
            if (!dbConfig.IsCreateDb || dbType == DataType.Sqlite)
            {
                return;
            }

            var db = new FreeSqlBuilder()
                    .UseConnectionString(dbType, dbConfig.CreateDbConn)
                    .Build();

            try
            {
                Console.WriteLine("\r\ncreate database started");
                await db.Ado.ExecuteNonQueryAsync(dbConfig.CreateDbSql);
                Console.WriteLine("create database succeed\r\n");
            }
            catch (Exception e)
            {
                Console.WriteLine($"create database failed.\n{e.Message}\r\n");
            }
        }

        private static DataType GetDbType(int dataType)
        {
            if (dataType == 0)
            {
                return DataType.MySql;
            }
            else if (dataType == 1)
            {
                return DataType.SqlServer;
            }
            else if (dataType == 2)
            {
                return DataType.PostgreSQL;
            }
            else if (dataType == 3)
            {
                return DataType.Oracle;
            }
            else if (dataType == 4)
            {
                return DataType.Sqlite;
            }
            else if (dataType == 5)
            {
                return DataType.OdbcOracle;
            }
            else if (dataType == 6)
            {
                return DataType.OdbcSqlServer;
            }
            else if (dataType == 7)
            {
                return DataType.OdbcMySql;
            }
            else if (dataType == 8)
            {
                return DataType.OdbcPostgreSQL;
            }
            else if (dataType == 9)
            {
                return DataType.Odbc;
            }
            else if (dataType == 10)
            {
                return DataType.OdbcDameng;
            }
            else if (dataType == 11)
            {
                return DataType.MsAccess;
            }
            else if (dataType == 12)
            {
                return DataType.Dameng;
            }
            else if (dataType == 13)
            {
                return DataType.OdbcKingbaseES;
            }
            else if (dataType == 14)
            {
                return DataType.ShenTong;
            }
            else if (dataType == 15)
            {
                return DataType.KingbaseES;
            }
            else if (dataType == 16)
            {
                return DataType.Firebird;
            }
            else
            {
                return DataType.Custom;
            }

        }
    }
}